package Day_0201.JUC;

/**
 * @author zxc
 * @date 2023/02/01 23:21
 **/
public class Optimistic_Pessimistic_Lock {
    public static void main(String[] args) {
        /**
         * 乐观锁 && 悲观锁
         * ===》
         * 1.悲观锁：
         * （1）概念 ：
         *  总是假设最坏的情况，每次去拿数据的时候都认为别人会修改，所以每次在拿数据的时候都会上锁，这样别人想拿这个数据就会阻塞直到它拿到锁。
         * （2）传统的关系型数据库里边就用到了很多这种锁机制，比如行锁，表锁等，读锁，写锁等，都是在做操作之前先上锁。
         *  再比如Java里面的同步原语synchronized关键字的实现也是悲观锁。
         *
         * 2.乐观锁：
         * （1）概念 ：
         *  顾名思义，就是很乐观，每次去拿数据的时候都认为别人不会修改，所以不会上锁，
         *  但是在更新的时候会判断一下在此期间别人有没有去更新这个数据，可以使用版本号等机制。
         * （2）乐观锁适用于多读的应用类型，这样可以提高吞吐量，像数据库提供的类似于write_condition机制，其实都是提供的乐观锁。
         *
         * 注意 ：在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。
         *
         * 3.乐观锁的实现方式：
         *（1）使用版本标识来确定读到的数据与提交时的数据是否一致。提交后修改版本标识，不一致时可以采取丢弃和再次尝试的策略。
         *
         *（2）Java中的Compare and Swap,即CAS操作实现乐观锁;
         * a.当多个线程尝试使用CAS同时更新同一个变量时，只有其中一个线程能更新变量的值，
         * b.而其它线程都失败，失败的线程并不会被挂起，而是被告知这次竞争中失败，并可以再次尝试。
         * ===》
         * CAS操作实现乐观锁的原理 ：
         * 即，多个线程尝试使用CAS操作同时更新一个变量时，只会有一个线程能够成功更新该变量的值;
         *
         * CAS 操作中包含三个操作数 ——
         * 需要读写的内存位置（V）;
         * 进行比较的预期原值（A）;
         * 拟写入的新值(B)。
         * 如果内存位置V的值与预期原值A相匹配，那么处理器会自动将该位置值更新为新值B。否则处理器不做任何操作。
         *
         * CAS缺点：
         * 1. ABA问题：
         * 比如说一个线程one从内存位置V中取出A，这时候另一个线程two也从内存中取出A，并且two进行了一些操作变成了B，
         * 然后two又将V位置的数据变成A，这时候线程one进行CAS操作发现内存中仍然是A，然后one操作成功。
         * 尽管线程one的CAS操作成功，但可能存在潜藏的问题。从Java1.5开始JDK的atomic包里提供了一个类AtomicStampedReference来解决ABA问题。
         *
         * 2. 循环时间长开销大：
         * 对于资源竞争严重（线程冲突严重）的情况，CAS自旋的概率会比较大，从而浪费更多的CPU资源，效率低于synchronized。
         *
         * 3. 只能保证一个共享变量的原子操作：
         * 当对一个共享变量执行操作时，我们可以使用循环CAS的方式来保证原子操作，
         * 但是对多个共享变量操作时，循环CAS就无法保证操作的原子性，这个时候就可以用锁。
         */
    }
}
